package com.yuand.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yuand.entity.SysRole;
import com.yuand.entity.SysRoleMenu;
import com.yuand.entity.SysUserRole;
import com.yuand.exception.ServiceException;
import com.yuand.mapper.SysRoleMapper;
import com.yuand.mapper.SysRoleMenuMapper;
import com.yuand.mapper.SysUserRoleMapper;
import com.yuand.service.SysRoleMenuService;
import com.yuand.service.SysRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuand.utils.ResponseResult;
import com.yuand.utils.WebUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author yuandong
 * @since 2022-01-14
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

	@Autowired
	private SysRoleMapper      sysRoleMapper;
	@Autowired
	private SysRoleMenuService sysRoleMenuService;
	@Autowired
	private SysRoleMenuMapper  sysRoleMenuMapper;
	@Autowired
	private SysUserRoleMapper sysUserRoleMapper;
	@Autowired
	private SysRoleService sysRoleService;


	/**
	 * 查询所有角色不分页
	 *
	 * @return
	 */
	public List<SysRole> selectAll() {
		return this.sysRoleMapper.selectList(null);
	}

	/**
	 * 查询所有角色-分页
	 *
	 * @param role
	 * @return
	 */
	@Override
	public List<SysRole> selectRoleList(SysRole role) {
		return this.sysRoleMapper.selectRoleList(role);
	}

	/**
	 * 新增角色
	 *
	 * @param role
	 */
	@Override
	public int add(SysRole role) {
		//保存角色
		int rows = this.sysRoleMapper.insert(role);

		Long[] menuIds = role.getMenuIds();
		List<SysRoleMenu> list = new ArrayList<>();
		//保存角色和菜单的关联
		if (menuIds.length > 0) {
			for (Long menuId : menuIds) {
				SysRoleMenu sysRoleMenu = new SysRoleMenu();
				sysRoleMenu.setRoleId(role.getRoleId());
				sysRoleMenu.setMenuId(menuId);
				list.add(sysRoleMenu);
			}
			this.sysRoleMenuService.saveBatch(list);
		}
		return rows;
	}

	/**
	 * 查询角色及关联的菜单信息
	 *
	 * @param roleId
	 * @return 2022-1-30 暂定用这种方式实现
	 * 另一种实现方式是用一条sql语句，在xml里面中使用<collection></collection>标签来实现
	 */
	public SysRole getRoleInfo(Long roleId) {
		SysRole sysRole = this.sysRoleMapper.selectById(roleId);
		//根据roleId查询对应的菜单(sys_role_menu)
		List<SysRoleMenu> list = this.sysRoleMenuMapper.selectList(new QueryWrapper<SysRoleMenu>().eq("role_id", roleId));

		if (!Objects.isNull(list)) {
			List<Long> menuList = list.stream().map(SysRoleMenu::getMenuId).collect(toList());
			//array.toArray(new String[array.size()]); list转数组
			Long[] menuIds = (Long[]) menuList.toArray(new Long[menuList.size()]);
			sysRole.setMenuIds(menuIds);
		}
		return sysRole;
	}

	/**
	 * 修改角色
	 *
	 * @param role
	 * @return
	 */
	public int edit(SysRole role) {
		//保存角色信息
		int row = this.sysRoleMapper.updateById(role);
		//删除角色和菜单的关联关系
		this.sysRoleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId());
		//重新插入
		this.insertRoleMenu(role);
		return row;
	}


	/**
	 * 根据用户id查询角色
	 * @param userId
	 * @return
	 */
	@Override
	public List<SysRole> selectRolesByUserId(Long userId) {
		//1.查询所有的角色
		List<SysRole> roles = this.sysRoleMapper.selectRoleList(new SysRole());
		//2.查询该用户已经勾选的角色(也即根据userId查询sys_user_role)表
		List<SysUserRole> userRoles = this.sysUserRoleMapper.selectList(new QueryWrapper<SysUserRole>().eq("user_id",userId));
		//3.循环遍历roles,将该用户已经勾选的角色置为true(也即将角色中的是否选中 flag设为true),对于嵌套的for循环，我们一般采取内大外小的原则
		for(SysUserRole userRole: userRoles){
			for(SysRole role: roles){
				if(userRole.getRoleId().longValue()==role.getRoleId().longValue()){
					role.setFlag(true);
					break;
				}
			}
		}
		return roles;
	}


	/**
	 * 取消用户的角色授权
	 * @param userRole
	 */
	public int cancelAuthUser(SysUserRole userRole){
		return this.sysUserRoleMapper.delete(new QueryWrapper<SysUserRole>().eq("user_id", userRole.getUserId()).eq("role_id", userRole.getRoleId()));
	}

	/**
	 * 根据roleIds删除角色
	 * @param roleIds
	 *
	 * 1：判断是否是管理员角色，如果是管理员角色则不能删除；
	 * 2：判断该角色是否已经绑定了用户，如果是则前台提示不能删除；
	 * 3：删除角色和菜单的关联关系；
	 * 4：删除角色和部门的关联关系；
	 */
	public void delRole(Long[] roleIds){

		for(Long roleId: roleIds){
			if(new SysRole(roleId).isAdmin()){
				throw new ServiceException("不允许操作超级管理员角色");
			}

			int flag = this.countUserRoleByRoleId(roleId);
			if(flag>0){
				throw new ServiceException("该角色已经关联用户，不能删除");
			}
		}

		//删除角色和菜单的关联关系
		this.sysRoleMenuService.remove(new QueryWrapper<SysRoleMenu>().in("role_id", roleIds));

		//删除角色
		this.sysRoleMapper.deleteBatchIds(Arrays.asList(roleIds));

	}


	/**
	 * 插入角色菜单关联关系
	 *
	 * @param role
	 */
	public void insertRoleMenu(SysRole role) {
		Long[] menuIds = role.getMenuIds();
		List<SysRoleMenu> roleMenus = new ArrayList<>();
		for (Long menuId : menuIds) {
			SysRoleMenu sysRoleMenu = new SysRoleMenu();
			sysRoleMenu.setRoleId(role.getRoleId());
			sysRoleMenu.setMenuId(menuId);
			roleMenus.add(sysRoleMenu);
		}
		if (roleMenus.size()>0) {
			this.sysRoleMenuService.saveBatch(roleMenus);
		}

	}


	/**
	 * 查询该角色在sys_user_role表中是否已经绑定了用户
	 * @param roleId
	 * @return
	 */
	public int countUserRoleByRoleId(Long roleId){
		return this.sysUserRoleMapper.selectCount(new QueryWrapper<SysUserRole>().eq("role_id",roleId));
	}


}
